//
//  WTTableViewController.m
//  Weather
//
//  Created by Scott on 26/01/2013.
//  Updated by Joshua Greene 16/12/2013.
//
//  Copyright (c) 2013 Scott Sherwood. All rights reserved.
//

#import "WTTableViewController.h"
#import "WeatherAnimationViewController.h"
#import "NSDictionary+weather.h"
#import "NSDictionary+weather_package.h"
#import "UIImageView+AFNetworking.h"

static NSString * const BaseURLString = @"https://www.raywenderlich.com/demos/weather_sample/";

@interface WTTableViewController ()
@property(strong) NSDictionary *weather;

@property(nonatomic, strong) NSMutableDictionary *currentDictionary; // current section being parsed
@property(nonatomic, strong) NSMutableDictionary *xmlWeather; // completed parsed xml response
@property(nonatomic, strong) NSString *elementName;
@property(nonatomic, strong) NSMutableString *outstring;
@end

@implementation WTTableViewController

- (id)initWithStyle:(UITableViewStyle)style
{
    self = [super initWithStyle:style];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.navigationController.toolbarHidden = NO;

    // Uncomment the following line to preserve selection between presentations.
    // self.clearsSelectionOnViewWillAppear = NO;
 
    // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
    // self.navigationItem.rightBarButtonItem = self.editButtonItem;
	
	self.locationManager = [[CLLocationManager alloc] init];
	self.locationManager.delegate = self;
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if([segue.identifier isEqualToString:@"WeatherDetailSegue"]){
        UITableViewCell *cell = (UITableViewCell *)sender;
        NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
        
        WeatherAnimationViewController *wac = (WeatherAnimationViewController *)segue.destinationViewController;
        
        NSDictionary *w;
        switch (indexPath.section) {
            case 0: {
                w = self.weather.currentCondition;
                break;
            }
            case 1: {
                w = [self.weather upcomingWeather][indexPath.row];
                break;
            }
            default: {
                break;
            }
        }
        wac.weatherDictionary = w;
    }
}

#pragma mark - Actions

- (IBAction)clear:(id)sender
{
    self.title = @"";
    self.weather = nil;
    [self.tableView reloadData];
}

- (IBAction)jsonTapped:(id)sender
{
	// 1
	NSString *string = [NSString stringWithFormat:@"%@weather.php?format=json", BaseURLString];
	NSURL *url = [NSURL URLWithString:string];
	NSURLRequest *request = [NSURLRequest requestWithURL:url];
	
	/*
	 AFHTTPRequestOperation is an all-in-one class for handling HTTP transfers across the network. You tell it that the response should be read as JSON by setting the responseSerializer property to the default JSON serializer. AFNetworking will then take care of parsing the JSON for you.
	 */
	// 2
	AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
	operation.responseSerializer = [AFJSONResponseSerializer serializer];
	[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
		
		// 3
		self.weather = (NSDictionary *)responseObject;
		self.title = @"JSON Retrieved";
		[self.tableView reloadData];
	} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
		
		// 4
		UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Error Retrieving Weather" 
																												message:[error localizedDescription] 
																											 delegate:nil 
																							cancelButtonTitle:@"Ok" 
																							otherButtonTitles:nil];
		[alertView show];
	}];
	
	// 5
	[operation start];
}

- (IBAction)plistTapped:(id)sender
{
	NSString *string = [NSString stringWithFormat:@"%@weather.php?format=plist", BaseURLString];
	NSURL *url = [NSURL URLWithString:string];
	NSURLRequest *request = [NSURLRequest requestWithURL:url];
	
	AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
	
	operation.responseSerializer = [AFPropertyListResponseSerializer serializer];
	
	[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
		
		self.weather = (NSDictionary *)responseObject;
		self.title = @"PLIST Retrieved";
		[self.tableView reloadData];
	} failure:^(AFHTTPRequestOperation *opration, NSError *error) {
		
		UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Error Retrieving Weather" 
																												message:[error localizedDescription] 
																											 delegate:nil 
																							cancelButtonTitle:@"Ok" 
																							otherButtonTitles:nil];
		[alertView show];
	}];
	
	[operation start];
}

- (IBAction)xmlTapped:(id)sender
{
	NSString *string = [NSString stringWithFormat:@"%@weather.php?format=xml", BaseURLString];
	NSURL *url = [NSURL URLWithString:string];
	NSURLRequest *request = [NSURLRequest requestWithURL:url];
	
	AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
	
	operation.responseSerializer = [AFXMLParserResponseSerializer serializer];
	
	[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
		
		NSXMLParser *XMLParse = (NSXMLParser *)responseObject;
		[XMLParse setShouldProcessNamespaces:YES];
		
		XMLParse.delegate = self;
		[XMLParse parse];
		
	} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
		
		UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Error Retrieving Weather" 
																												message:[error localizedDescription] 
																											 delegate:nil 
																							cancelButtonTitle:@"Ok" 
																							otherButtonTitles:nil];
		[alertView show];
	}];
	
	[operation start];
}

- (IBAction)clientTapped:(id)sender
{	
	NSURL *baseURL = [NSURL URLWithString:BaseURLString];
	NSDictionary *parameters = @{@"format": @"json"};
	
	AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc] initWithBaseURL:baseURL];
	manager.responseSerializer = [AFJSONResponseSerializer serializer];
	
	UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"AFHTTPSessionManager" 
																																 message:nil 
																													preferredStyle:UIAlertControllerStyleActionSheet];
	UIAlertAction *cancelButton = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil];
	
	UIAlertAction *httpGetButton = [UIAlertAction actionWithTitle:@"HTTP GET" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
		[manager GET:@"weather.php" parameters:parameters success:^(NSURLSessionDataTask * _Nonnull task, id  _Nonnull responseObject) {
			
			NSLog(@"httpGet.weather=%@", responseObject);
			
			self.weather = responseObject;
			self.title = @"HTTP GET";
			[self.tableView reloadData];
		} failure:^(NSURLSessionDataTask * _Nonnull task, NSError * _Nonnull error) {
			UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Error Retrieving Weather" 
																																		 message:[error localizedDescription] 
																															preferredStyle:UIAlertControllerStyleAlert];
			UIAlertAction *okButton = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil];
			[alert addAction:okButton];
			[self presentViewController:alert animated:YES completion:nil];
		}];
	}];
	
	UIAlertAction *httpPostButton = [UIAlertAction actionWithTitle:@"HTTP POST" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
		[manager POST:@"weather.php" parameters:parameters success:^(NSURLSessionDataTask * _Nonnull task, id  _Nonnull responseObject) {
			self.weather = responseObject;
			self.title = @"HTTP POST";
			[self.tableView reloadData];
		} failure:^(NSURLSessionDataTask * _Nonnull task, NSError * _Nonnull error) {
			UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Error Retrieving Weather" 
																																		 message:[error localizedDescription] 
																															preferredStyle:UIAlertControllerStyleAlert];
			UIAlertAction *okButton = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil];
			[alert addAction:okButton];
			[self presentViewController:alert animated:YES completion:nil];
		}];
	}];
	
	[alert addAction:cancelButton];
	[alert addAction:httpGetButton];
	[alert addAction:httpPostButton];
	[self presentViewController:alert animated:YES completion:nil];
}

- (IBAction)apiTapped:(id)sender
{
	NSLog(@"apiTapped");
	
	if ([[[UIDevice currentDevice] systemVersion] doubleValue] > 8.0) {
		//设置定位权限 仅ios8有意义
		[self.locationManager requestWhenInUseAuthorization];// 前台定位
	
		//  [locationManager requestAlwaysAuthorization];// 前后台同时定位
	}
	[self.locationManager startUpdatingLocation];
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 2;
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section 
{
	if (section == 0) {
		return @"currentCondition";
	} else {
		return @"upcomingWeather";
	}
	return @"undefined";
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
	if (!self.weather) {
		return 0;
	}
	
	switch (section) {
  case 0: {
		return 1;
	}
	case 1: {
		NSArray *upcomingWeather = [self.weather upcomingWeather];
		return [upcomingWeather count];
	}
  default:
			return 0;
	}
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
	static NSString *CellIdentifier = @"WeatherCell";
	UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
	
	NSDictionary *daysWeather = nil;
	
	switch (indexPath.section) {
  case 0: {
		daysWeather = [self.weather currentCondition];
		break;
	}
			
	case 1: {
		NSArray *upcomingWeather = [self.weather upcomingWeather];
		daysWeather = upcomingWeather[indexPath.row];
		break;
	}
			
  default:
			break;
	}
	
	cell.textLabel.text = [daysWeather weatherDescription];
	
	NSURL *url = [NSURL URLWithString:daysWeather.weatherIconURL];
	NSURLRequest *request = [NSURLRequest requestWithURL:url];
	UIImage *placeholderImage = [UIImage imageNamed:@"placeholder"];
	
//	NSLog(@"imageURL:%@", request);
	
	__weak UITableViewCell *weakCell = cell;
	[cell.imageView setImageWithURLRequest:request
												placeholderImage:placeholderImage
																 success:^(NSURLRequest * request, NSHTTPURLResponse * response, UIImage * image) {
																	 weakCell.imageView.image = image;
																	 [weakCell setNeedsLayout];
																 } 
																 failure:nil];
		
	return cell;
}


#pragma mark - Table view delegate

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Navigation logic may go here. Create and push another view controller.
}


#pragma mark - NSXMLParser delegate

/*
 The parser calls this method when it first starts parsing. When this happens, you set self.xmlWeather to a new dictionary, which will hold the XML data.
 */
- (void)parserDidStartDocument:(NSXMLParser *)parser 
{
	self.xmlWeather = [NSMutableDictionary dictionary];
}

/*
 The parser calls this method when it finds a new element start tag. When this happens, you keep track of the new element’s name as self.elementName and then set self.currentDictionary to a new dictionary if the element name represents the start of a new weather forecast. You also reset outstring as a new mutable string in preparation for new XML to be received related to the element.
 */
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict 
{
	self.elementName = qName;
	
	if ([qName isEqualToString:@"current_condition"] || 
			[qName isEqualToString:@"weather"] || 
			[qName isEqualToString:@"request"]) {
		self.currentDictionary = [NSMutableDictionary dictionary];
	}
	
	self.outstring = [NSMutableString string];
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
	if (!self.elementName) {
		return;
	}
	
	[self.outstring appendFormat:@"%@", string];
}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
	/*
	 1.The current_condition element indicates you have the weather for the current day. You add this directly to the xmlWeather dictionary.
	 2.The weather element means you have the weather for a subsequent day. While there is only one current day, there may be several subsequent days, so you add this weather information to an array.
	 3.The value tag only appears inside other tags, so it’s safe to skip over it.
	 4.The weatherDesc and weatherIconUrl element values need to be boxed inside an array before they can be stored. This way, they will match how the JSON and plist versions of the data are structured exactly.
	 5.All other elements can be stored as is.
	 */
	
	// 1
	if ([qName isEqualToString:@"current_condition"] ||
			[qName isEqualToString:@"request"]) {
		self.xmlWeather[qName] = @[self.currentDictionary];
		self.currentDictionary = nil;
	}
	// 2
	else if ([qName isEqualToString:@"weather"]) {
		// initialize the list of weather items if it doesn't exsit
		NSMutableArray *array = self.xmlWeather[@"weather"] ?: [NSMutableArray array];
		
		// add the current weather object
		[array addObject:self.currentDictionary];
		
		// set the new array to the "weather" key on xmlWeather dictionary
		self.xmlWeather[@"weather"] = array;
		
		self.currentDictionary = nil;
	}
	// 3
	else if ([qName isEqualToString:@"value"]) {
		// Ignore value tags, they only appear in the two conditions below
	}
	// 4
	else if ([qName isEqualToString:@"weatherDesc"] ||
					 [qName isEqualToString:@"weatherIconUrl"]) {
		NSDictionary *dictionary = @{@"value": self.outstring};
		NSArray *array = @[dictionary];
		self.currentDictionary[qName] = array;
	}
	// 5
	else if (qName) {
		self.currentDictionary[qName] = self.outstring;
	}
	
	self.elementName = nil;
}

- (void)parserDidEndDocument:(NSXMLParser *)parser
{
	self.weather = @{@"data": self.xmlWeather};
	self.title = @"XML Retrieved";
	[self.tableView reloadData];
}

#pragma mark - Core Location Manager delegate
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
{
	NSLog(@"didUpdateLocations");
	
	// Last object contains the most recent location
	CLLocation *newLocation = [locations lastObject];
	
	// If the location is more than 5 minutes old, ignore it
	if ([newLocation.timestamp timeIntervalSinceNow] > 300) {
		return;
	}
	
	[self.locationManager stopUpdatingLocation];
	
	WeatherHTTPClient *client = [WeatherHTTPClient sharedWeatherHTTPClient];
	client.delegate = self;
	[client updateWeatherAtLocation:newLocation forNumberOfDays:5];
}

#pragma mark - WeatherHTTPClientDelegate protocol
- (void)weatherHTTPClient:(WeatherHTTPClient *)client didUpdateWithWeather:(id)weather
{
	NSLog(@"didUpdateWithWeather:%@", weather);
	
	self.weather = weather;
	self.title = @"API Updated";
	[self.tableView reloadData];
}

- (void)weatherHTTPClient:(WeatherHTTPClient *)client didFailWithError:(NSError *)error
{
	UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Error Retrieving Weather" 
																																 message:[NSString stringWithFormat:@"%@", error] 
																													preferredStyle:UIAlertControllerStyleAlert];
	UIAlertAction *okButton = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil];
	[alert addAction:okButton];
	[self presentViewController:alert animated:YES completion:nil];
}

@end